
package com.zy.je.common.core.service;

import com.zy.je.common.core.utils.CheckUtil;
import com.zy.je.common.core.utils.lang.ObjectUtil;
import com.zy.je.common.core.web.rest.RestResult;
import com.zy.je.common.core.web.rest.ResultStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * @author zy
 */
public interface CommonService {
    Logger logger = LoggerFactory.getLogger(CommonService.class);

    default <P, R> R callRemoteService(Function<P, RestResult<R>> fn, P p) {
        RestResult<R> resp = fn.apply(p);
        checkResp(resp);
        return resp.getData();
    }

    default <P1, P2, R> R callRemoteService(BiFunction<P1, P2, RestResult<R>> fn, P1 p1, P2 p2) {
        RestResult<R> resp = fn.apply(p1, p2);
        checkResp(resp);
        return resp.getData();
    }

    default <P1, P2, P3, R> R callRemoteService(Function3<P1, P2, P3, RestResult<R>> fn, P1 p1, P2 p2, P3 p3) {
        RestResult<R> resp = fn.apply(p1, p2, p3);
        checkResp(resp);
        return resp.getData();
    }

    default <R> R callRemoteService(Supplier<RestResult<R>> fn) {
        RestResult<R> resp = fn.get();
        checkResp(resp);
        return resp.getData();
    }

    default <R> void checkResp(RestResult<R> resp) {
        ResultStatus status = ResultStatus.getInstance(
                ObjectUtil.toInteger(Optional.ofNullable(resp).map(it -> it.getCode()).orElse(null), ResultStatus.CALL_INNER_ERROR.getCode())
        );

        if (!ResultStatus.OK.getCode().equals(status.getCode())) {
            CheckUtil.check(status,true, status,
                    Optional.ofNullable(resp).map(it -> it.getDescription()).orElse(null));
            // logger.info("内部服务调用出错(param:p1={},p2={},response:{})", JSONUtil.toJsonStr(p1), JSONUtil.toJsonStr(p2), JSONUtil.toJsonStr(resp));
        }
    }


    @FunctionalInterface
    interface Function3<P1, P2, P3, R> {
        public R apply(P1 p1, P2 p2, P3 p3);
    }
}
